package com.kclm.xsap.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.kclm.xsap.dao.ClassRecordDao;
import com.kclm.xsap.dao.CourseDao;
import com.kclm.xsap.dao.ReservationRecordDao;
import com.kclm.xsap.dao.ScheduleRecordDao;
import com.kclm.xsap.entity.*;
import com.kclm.xsap.service.*;
import com.kclm.xsap.utils.R;
import com.kclm.xsap.utils.exception.RRException;
import com.kclm.xsap.utils.exception.ServiceException;
import com.kclm.xsap.utils.time.ClassTimeUtil;
import com.kclm.xsap.utils.time.JudgeTimeUtils;
import com.kclm.xsap.vo.ConsumeFormVo;
import com.kclm.xsap.vo.ScheduleDetailReservedVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Slf4j
@Service
public class ScheduleRecordServiceImpl extends ServiceImpl<ScheduleRecordDao, ScheduleRecordEntity> implements ScheduleRecordService {
    @Autowired
    private CourseDao courseDao;
    @Autowired
    private ScheduleRecordDao scheduleRecordDao;
    @Autowired
    private ClassRecordDao classRecordDao;
    @Autowired
    private ReservationRecordDao reservationRecordDao;
    @Autowired
    private MemberCardService memberCardService;

    @Override
    public List<ScheduleRecordEntity> getSameDateSchedule(LocalDate now) {
        return null;
    }

    @Override
    public String getresName(Long scheduleId) {
        return baseMapper.selectresName(scheduleId);
    }

    @Override
    public List<String> selectCards(Long id) {
        return baseMapper.selectCards(id);
    }

    @Override
    public boolean saveOrNot(ScheduleRecordEntity scheduleRecordEntity) {

        log.info("Service==>scheduleRecordEntity==>{}" + scheduleRecordEntity);

        //获取当前日期
        LocalDate nowDate = LocalDateTime.now().toLocalDate();
        log.info("nowDate===>{}" + nowDate);
        //获取当前时间:时:分:秒
        //LocalTime nowTime = LocalTime.parse(LocalDateTime.now().toLocalTime().format(DateTimeFormatter.ofPattern("HH:mm:ss")));
        //log.info("nowTime===>{}" + nowTime);


        //获取课程开始日期
        LocalDate startDate = scheduleRecordEntity.getStartDate();
        //获取课程开始时间
        LocalTime classStartTime = scheduleRecordEntity.getClassTime();

        //classStartTime不能早于8:00不能晚于21:00
        if (classStartTime.isBefore(LocalTime.parse("08:00:00")) || classStartTime.isAfter(LocalTime.parse("21:00:00"))) {
            log.info("经过判断，课程开始时间不能早于8:00不能晚于21:00！");
            //throw new ServiceException("课程开始时间不能早于8:00不能晚于21:00！");
        }

        //判断开始日期不能晚于当前日期
        if (nowDate.isAfter(startDate)) {
            log.info("经过判断，开始日期不能晚于当前日期！");
            //throw new ServiceException("开始日期不能晚于当前日期！");
        }

        //计算新增的排课开始时间和结束时间
        // 根据课程ID查询课程信息
        CourseEntity course = courseDao.selectById(scheduleRecordEntity.getCourseId());
        // 创建一个存储教师课程安排时间的列表
        List<TimeEntity> teacherScheduleEntityList = new ArrayList<>();
        // 根据前端传来的时间计算课程开始时间和结束时间
        //LocalTime classStartTime = scheduleRecordEntity.getClassTime();
        //课程本身时间加上10分钟，避免课程时间冲突
        LocalTime classEndTime = classStartTime.plusMinutes(course.getDuration() + 10);
        TimeEntity classTime = new TimeEntity(classStartTime, classEndTime);

        //遍历已有的课程安排时间列表，计算教师上课时间和下课时间
        log.info("排课日期===>" + scheduleRecordEntity.getStartDate());
        // 根据教师ID和开始日期查询课程安排记录
        List<ScheduleRecordEntity> scheduleRecordEntityList = scheduleRecordDao.selectList(
                new QueryWrapper<ScheduleRecordEntity>()
                        .eq("teacher_id", scheduleRecordEntity.getTeacherId())
                        .eq("start_date", scheduleRecordEntity.getStartDate()));
        // 遍历查询到的教师课程安排记录
        for (ScheduleRecordEntity recordEntity : scheduleRecordEntityList) {
            // 根据课程ID查询课程信息
            CourseEntity courseEntity = courseDao.selectById(recordEntity.getCourseId());
            // 计算教师上课时间和下课时间
            LocalTime teacherStartTime = recordEntity.getClassTime();
            //上课结束后增加10分钟时间，避免课程时间冲突
            LocalTime teacherEndTime = teacherStartTime.plusMinutes(courseEntity.getDuration() + 10);
            TimeEntity timeEntity = new TimeEntity(teacherStartTime, teacherEndTime);
            teacherScheduleEntityList.add(timeEntity); // 将教师课程安排时间添加到列表中
        }

        ///////////////////////////////////////////
//        // 对教师课程安排时间列表进行排序
//        Collections.sort(teacherSchedule, new TimeComparator());
//
//        // 打印排序后的教师课程安排时间列表
//        System.out.println("教师课程安排时间列表：");
//        System.out.println("teacherSchedule===>" + teacherSchedule);
//
//        // 检查课程时间是否可以添加
//        boolean flag = ClassTimeUtil.isAdd(teacherSchedule, classTime);
        ////////////////////////////////////////////////////////////////
        boolean flag = JudgeTimeUtils.judgeTime(teacherScheduleEntityList, classTime);
        if (flag) {
            return true;
        } else {
            throw new ServiceException("该时间段已有课，请重新选择时间！");
            //return false;
        }
    }

    // 自定义比较器
    public class TimeComparator implements Comparator<TimeEntity> {
        @Override
        public int compare(TimeEntity te1, TimeEntity te2) {
            // 首先根据startTime进行排序
            int startTimeComparison = te2.getStartTime().compareTo(te1.getStartTime());
            // 如果startTime相同，则根据endTime进行排序
            if (startTimeComparison == 0) {
                return te2.getEndTime().compareTo(te1.getEndTime());
            }
            return startTimeComparison;
        }
    }


    @Override
    public boolean isEnsureAll(Long id) {
        // 查询未消费的课程记录列表
        List<ClassRecordEntity> classRecordEntityList = classRecordDao.selectList(
                new QueryWrapper<ClassRecordEntity>()
                        .eq("schedule_id", id)
                        .eq("check_status", 0) // 未审核状态
                        .eq("reserve_check", 0)); // 预约未确认状态

        // 如果课程记录列表为空，则返回false，表示没有未确认的课程记录
        if (classRecordEntityList.isEmpty()) {
            return false;
        }

        // 获取课程记录列表中的第一条课程记录
        ClassRecordEntity classRecordEntity = classRecordEntityList.stream().findFirst().orElse(null);
        // 根据课程记录获取课程安排信息
        ScheduleRecordEntity scheduleRecordEntity = scheduleRecordDao.selectById(classRecordEntity.getScheduleId());
        // 获取课程开始时间
        LocalDateTime startTime = LocalDateTime.of(scheduleRecordEntity.getStartDate(), scheduleRecordEntity.getClassTime());
        // 根据课程安排获取课程信息
        CourseEntity courseEntity = courseDao.selectById(scheduleRecordEntity.getCourseId());
        // 计算课程结束时间，加上课程时长和额外的10分钟（可能是课程间的休息时间或者其他处理时间）
        LocalDateTime endTime = startTime.plusMinutes(courseEntity.getDuration() + 10);
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();
        // 打印调试信息
        System.out.println("课程结束时间：" + endTime);
        System.out.println("当前时间：" + now);
        System.out.println("是否晚于课程开始时间：" + now.isAfter(endTime));
        // 如果当前时间晚于课程结束时间，则返回true，表示所有未确认的课程已经结束
        if (now.isAfter(endTime)) {
            return true;
        } else {
            return false;
        }
    }


    @Override
    public boolean isConsum(Long id, String name) {
        // 查询未消费的课程记录列表
        List<ClassRecordEntity> classRecordEntityList = classRecordDao.selectList(
                new QueryWrapper<ClassRecordEntity>()
                        .eq("schedule_id", id)
                        .eq("check_status", 0) // 未审核状态
                        .eq("reserve_check", 0)); // 预约未确认状态

        int count = 0; // 计数器，用于记录成功消费的次数
        for (ClassRecordEntity recordEntity : classRecordEntityList) {
            // 根据会员ID和课程安排ID查询课程记录
            ClassRecordEntity classRecord = classRecordDao.selectOne(
                    new QueryWrapper<ClassRecordEntity>()
                            .eq("member_id", recordEntity.getMemberId())
                            .eq("schedule_id", recordEntity.getScheduleId()));

            // 根据会员ID和课程安排ID查询预约记录
            ReservationRecordEntity reservationRecordEntity = reservationRecordDao.selectOne(
                    new QueryWrapper<ReservationRecordEntity>()
                            .eq("member_id", recordEntity.getMemberId())
                            .eq("schedule_id", recordEntity.getScheduleId()));

            // 根据课程安排ID查询课程信息
            CourseEntity courseEntity = courseDao.selectById(
                    scheduleRecordDao.selectById(recordEntity.getScheduleId()).getCourseId());

            // 创建消费表单数据对象
            ConsumeFormVo consumeFormVo = new ConsumeFormVo();
            // 转换数据类型
            BigDecimal bigDecimal = new BigDecimal(String.valueOf(courseEntity.getMoney()));
            BigDecimal result = bigDecimal.multiply(new BigDecimal(reservationRecordEntity.getReserveNums())); // 计算消费金额

            // 设置消费表单数据
            consumeFormVo.setMemberId(recordEntity.getMemberId())
                    .setCardBindId(classRecord.getBindCardId())
                    .setOperator(name) // 设置操作员姓名
                    .setScheduleId(recordEntity.getScheduleId())
                    .setAmountOfConsumption(result) // 设置消费金额
                    .setCardCountChange(courseEntity.getTimesCost() * reservationRecordEntity.getReserveNums()) // 设置卡次变动
                    .setNote(recordEntity.getNote()); // 设置备注

            // 调用会员卡服务执行消费操作
            if (memberCardService.consum(consumeFormVo)) {
                ++count;
            }
        }

        // 如果成功消费次数等于未消费课程记录列表的大小，则返回true，表示所有课程都成功消费了
        if (count == classRecordEntityList.size()) {
            return true;
        } else {
            return false;
        }
    }


    @Override
    public boolean isDelete(Integer id) {
        ScheduleRecordEntity scheduleRecordEntity = scheduleRecordDao.selectById(id);
        if (scheduleRecordEntity.getOrderNums() == 0) {
            try {
                scheduleRecordDao.deleteById(id);
            } catch (Exception e) {
                throw new ServiceException("删除课程记录失败！");
            }
            return true;
        } else {
            return false;

        }
    }

    @Override
    public boolean isCopy(String sourceDateStr, String targetDateStr, List<ScheduleRecordEntity> scheduleRecordEntityList) {
        List<ScheduleRecordEntity> targetRecordEntityList = scheduleRecordDao.selectList(
                new QueryWrapper<ScheduleRecordEntity>().eq("start_date", targetDateStr));
        //如果复制那天没有课，直接复制成功
        if (targetRecordEntityList.isEmpty()) {
            return true;
        } else {
            int count = 0;
            //先判断两个集合之中老师的id，再判断老师上课时间段是否冲突（上课开始时间+课程时间+下课时间（10））
            for (ScheduleRecordEntity scheduleRecordEntity : scheduleRecordEntityList) {
                for (ScheduleRecordEntity targetRecordEntity : targetRecordEntityList) {
                    if (scheduleRecordEntity.getTeacherId() == targetRecordEntity.getTeacherId()) {
                        LocalDateTime copyTimeStart = LocalDateTime.of(scheduleRecordEntity.getStartDate(), scheduleRecordEntity.getClassTime());
                        CourseEntity courseEntity = courseDao.selectById(targetRecordEntity.getCourseId());
                        LocalDateTime startTime = LocalDateTime.of(targetRecordEntity.getStartDate(), targetRecordEntity.getClassTime());
                        LocalDateTime endTime = startTime.plusMinutes(courseEntity.getDuration() + 10);
                        if ((copyTimeStart.isEqual(startTime) || copyTimeStart.isAfter(startTime)) &&
                                copyTimeStart.isBefore(endTime)) {
                            ++count;
                        }
                    }
                }
            }
            if (count > 0) {
                return false;
            } else {
                return true;
            }
        }
    }
}
